package com.xbongbong.workorder.abstracts;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.help.log.InsertDataLogHelp;
import com.xbongbong.paas.constant.MessageConstant;
import com.xbongbong.paas.data.service.CabinetFileService;
import com.xbongbong.paas.data.service.RichTextService;
import com.xbongbong.paas.domain.entity.PaasFormDataEntity;
import com.xbongbong.paas.domain.entity.PaasProcessDataEntity;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.enums.IndexTypeEnum;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.help.FormDataHelp;
import com.xbongbong.paas.help.FormDataValidateDataHelp;
import com.xbongbong.paas.help.ProSaveHelp;
import com.xbongbong.paas.pojo.dto.FormDataUpdateDTO;
import com.xbongbong.paas.pojo.dto.SaasFormSaveDTO;
import com.xbongbong.paas.pojo.dto.ValidateDataDTO;
import com.xbongbong.paas.pojo.vo.FormDataUpdateVO;
import com.xbongbong.paas.service.workflow.trigger.WorkflowFormDataOperationService;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.paas.toolbox.wrap.UserVO;
import com.xbongbong.paas.util.FormDataUtil;
import com.xbongbong.parent.abstracts.AbstractParentUpdateFormDataService;
import com.xbongbong.parent.pojo.UpdateValidateReturnPojo;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.formdata.pojo.vo.BeforeUpdateVO;
import com.xbongbong.pro.formdata.pojo.vo.UpdateVO;
import com.xbongbong.pro.permission.pojo.dto.VerifyUpdatePermissionDTO;
import com.xbongbong.saas.domain.entity.WorkOrderEntity;
import com.xbongbong.saas.domain.entity.ext.WorkOrderExplainEntityExt;
import com.xbongbong.saas.domain.entity.ext.WorkOrderFormEntityExt;
import com.xbongbong.saas.enums.OperateModuleTypeEnum;
import com.xbongbong.saas.enums.OperateTypeEnum;
import com.xbongbong.saas.enums.RedundantTemplateTypeEnum;
import com.xbongbong.saas.enums.ShowTypeEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.help.AnalyticalHelp;
import com.xbongbong.saas.model.WorkOrderExplainModel;
import com.xbongbong.saas.model.WorkOrderFormModel;
import com.xbongbong.saas.model.WorkOrderModel;
import com.xbongbong.sys.help.ProPermissionHelp;
import com.xbongbong.util.ImportDataUtil;
import com.xbongbong.workflow.domain.entity.WorkflowBackupDataEntity;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * @author 吴峰
 * @date 2022/01/11 9:54
 */
@Component
public abstract class AbstractWorkOrderUpdateDataService extends AbstractParentUpdateFormDataService<WorkOrderFormEntityExt, WorkOrderEntity> {


    @Resource
    private WorkflowFormDataOperationService workflowFormDataOperationService;
    @Resource
    private InsertDataLogHelp insertDataLogHelp;
    @Resource
    private CabinetFileService cabinetFileService;
    @Resource
    private WorkOrderFormModel workOrderFormModel;
    @Resource
    private WorkOrderExplainModel workOrderExplainModel;
    @Resource
    private WorkOrderModel workOrderModel;
    @Resource
    private FormDataValidateDataHelp formDataValidateDataHelp;
    @Resource
    private AnalyticalHelp analyticalHelp;
    @Resource
    private RichTextService richTextService;
    @Resource
    private FormDataHelp formDataHelp;

    /**
     * 更新表单富文本
     *
     * @param formDataUpdateDTO
     * @param richTextData
     * @return
     */
    protected Integer updateFormRichText(FormDataUpdateDTO formDataUpdateDTO, Object richTextData) {
        return richTextService.updateFormRichText(formDataUpdateDTO, richTextData);
    }

    /**
     * 移除富文本
     *
     * @param data Json数据
     * @return 富文本数据
     */
    protected Object removeRichText(JSONObject data){
        return FormDataUtil.removeRichText(data);
    }

    /**
     * 备份富文本
     *
     * @param workflowBackupDataEntity
     * @param businessType
     * @param saasMark
     */
    protected void backupRichText(WorkflowBackupDataEntity workflowBackupDataEntity, Integer businessType, Integer saasMark){
        richTextService.backupRichText(workflowBackupDataEntity, businessType, saasMark);
    }

    @Override
    public void validatePermission(FormDataUpdateDTO formDataUpdateDTO) throws XbbException {
        boolean isImport = Objects.equals(formDataUpdateDTO.getIsImport(), 1);
        if ( isImport ) {
            return;
        }
        // 编辑权限校验
        VerifyUpdatePermissionDTO verifyUpdatePermissionDTO = new VerifyUpdatePermissionDTO();
        BeanUtil.copyProperties(formDataUpdateDTO, verifyUpdatePermissionDTO);
        ProPermissionHelp.verifyEditPermission(verifyUpdatePermissionDTO);
    }

    @Override
    public WorkOrderFormEntityExt getForm(FormDataUpdateDTO formDataUpdateDTO) throws XbbException {
        WorkOrderFormEntityExt workOrderFormEntityExt = workOrderFormModel.getByKey(formDataUpdateDTO.getFormId(), formDataUpdateDTO.getCorpid());
        if ( Objects.isNull(workOrderFormEntityExt) ) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_NOT_EXIST);
        }
        return workOrderFormEntityExt;
    }

    @Override
    public WorkOrderEntity getFormData(FormDataUpdateDTO formDataUpdateDTO, Map<String, FieldAttrEntity> explainMap) throws XbbException {
        WorkOrderEntity workOrderEntity = workOrderModel.getByKey(formDataUpdateDTO.getDataId(), formDataUpdateDTO.getCorpid());
        if ( Objects.isNull(workOrderEntity) || Objects.equals(workOrderEntity.getDel(), DelEnum.DELETE.getDel()) ) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_DATA_NOT_EXIST);
        }
        //现在除了需要判断当前人有没有这个业务编辑的表单权限，还需要判断有没有这条数据的编辑权限，外联那边通过按钮控制不住，所以这边统一做校验
        handleEditDataPermission(formDataUpdateDTO,explainMap, workOrderEntity);

        return workOrderEntity;
    }

    @Override
    public List<FieldAttrEntity> getExplainList(FormDataUpdateDTO formDataUpdateDTO, String corpid, Long formId, Integer saasMark, Integer businessType) throws XbbException {
        WorkOrderExplainEntityExt workOrderExplainEntity = workOrderExplainModel.getByFormId(formId, corpid);
        if ( Objects.isNull(workOrderExplainEntity) ) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_DATA_NOT_EXIST);
        }
        //保证数据正确
        formDataUpdateDTO.setAppId(workOrderExplainEntity.getAppId());
        formDataUpdateDTO.setMenuId(workOrderExplainEntity.getMenuId());
        formDataUpdateDTO.setFormId(workOrderExplainEntity.getFormId());
        return JSON.parseArray(workOrderExplainEntity.getExplains(), FieldAttrEntity.class);
    }


    @Override
    public UpdateValidateReturnPojo analyticalData(FormDataUpdateDTO formDataUpdateDTO, ValidateDataDTO validateDataDTO, WorkOrderEntity workOrderEntity, Map<String, FieldAttrEntity> explainMap) throws XbbException {
        ProSaveHelp.analyticalData(validateDataDTO);
        formDataValidateDataHelp.validateData(validateDataDTO);
        validateDataDTO.setCreatorId(workOrderEntity.getCreatorId());
        validateDataDTO.setOldOwnerId(workOrderEntity.getOwnerId());
        validateDataDTO.setPaasFormDataEntity(workOrderEntity);
        //isNew标识代表是不是新增 true代表新增 false代表编辑
        validateDataDTO.setIsNew(false);
        analyticalHelp.beforeSave(validateDataDTO);
        // 存放所属部门
        formDataUpdateDTO.setDepartmentId(validateDataDTO.getDepartmentId());
        return new UpdateValidateReturnPojo();
    }

    @Override
    public void importAnalyticalData(ValidateDataDTO validateDataDTO, WorkOrderEntity workOrderEntity, Map<String, FieldAttrEntity> explainMap, FormDataUpdateDTO formDataUpdateDTO) throws XbbException {
        ProSaveHelp.analyticalData(validateDataDTO);
        formDataValidateDataHelp.validateData(validateDataDTO);
        // 先放回原值
        importSetData(validateDataDTO, explainMap, workOrderEntity, validateDataDTO.getData(), formDataUpdateDTO.getAttrList());
        //
        validateDataDTO.setCreatorId(workOrderEntity.getCreatorId());
        validateDataDTO.setOldOwnerId(workOrderEntity.getOwnerId());
        validateDataDTO.setPaasFormDataEntity(workOrderEntity);
        //isNew标识代表是不是新增 true代表新增 false代表编辑
        validateDataDTO.setIsNew(false);
        analyticalHelp.beforeSave(validateDataDTO);
    }


    @Override
    public boolean isEnableNewWorkflow(FormDataUpdateDTO formDataUpdateDTO, Map<String, FieldAttrEntity> explainMap, WorkOrderEntity paasFormDataEntity, WorkOrderEntity oldPaasFormData) throws XbbException {
        return workflowFormDataOperationService.isEnableNewWorkflow(formDataUpdateDTO, explainMap, paasFormDataEntity, oldPaasFormData);
    }


    @Override
    public void workflowUpdateTrigger(FormDataUpdateDTO formDataUpdateDTO, BeforeUpdateVO beforeSaveVO, FormDataUpdateVO formDataSaveVO, WorkOrderEntity paasFormDataEntity, WorkOrderEntity oldPaasFormDataEntity) throws XbbException {
        workflowFormDataOperationService.workflowUpdateTrigger(formDataUpdateDTO, beforeSaveVO, formDataSaveVO);
    }


    @Override
    public void importSetData(ValidateDataDTO validateDataDTO, Map<String, FieldAttrEntity> explainMap, WorkOrderEntity oldDataEntity, JSONObject newData, List<String> attrList) throws XbbException {
        JSONObject oldData = oldDataEntity.getData();
        explainMap.forEach((key, value) -> {
            //判断无需覆盖字段
            boolean notImport = ((Objects.equals(value.getIsRedundant(), 0)
                    && (!ShowTypeEnum.getAddShowType().contains(value.getShowType()))
                    || StringUtil.isNotEmpty(value.getUnableEditMemo())) ||
                    FieldTypeEnum.getUnnecessaryFieldType().contains(value.getFieldType()));
            if (!notImport) {
                // 业务层无需覆盖字段逻辑
                businessImportSetData(value, oldData, newData);
            } else {
                newData.put(key, oldData.get(key));
            }

            if (Objects.isNull(newData.get(key))) {
                // 置空是为了清掉es中的数据
                newData.put(key, null);
            }
        });
        if (CollectionsUtil.isNotEmpty(attrList)) {
            // oldData的旧值赋给newData里
            ImportDataUtil.setOldData(newData, oldData, attrList);
            ImportDataUtil.setOldDepartmentId(oldDataEntity.getDepartmentId(), validateDataDTO.getDepartmentId(), explainMap, attrList);
        }
    }

    @Override
    public void saveFile(Map<String, FieldAttrEntity> explainMap, WorkOrderEntity workOrderEntity, Integer businessType, UserVO userVO) throws XbbException {
        //文件柜数据保存
        cabinetFileService.saveDataCabinetFile(explainMap, workOrderEntity.getData(), workOrderEntity.getSubFormData(), userVO.getCorpid(),
                workOrderEntity.getDataId(), XbbRefTypeEnum.WORK_ORDER.getCode(), userVO.getUserId());
    }


    public void saveLogger(FormDataUpdateDTO formDataUpdateDTO, PaasFormDataEntity paasFormDataEntity, RedundantTemplateTypeEnum redundantTemplateTypeEnum, String logMemo,
                           String opObjectName, OperateModuleTypeEnum operateModuleTypeEnum, UpdateVO updateVO,
                           BeforeUpdateVO beforeUpdateVO, OperateTypeEnum operateTypeEnum, IndexTypeEnum indexTypeEnum) {
        insertDataLogHelp.saveLogger(formDataUpdateDTO, paasFormDataEntity, redundantTemplateTypeEnum, logMemo, opObjectName, operateModuleTypeEnum, updateVO, beforeUpdateVO, operateTypeEnum, indexTypeEnum);
    }


    /**
     * 更新保存后封装入参
     *
     * @param saasFormSaveDTO       保存实体后逻辑入参
     * @param paasFormDataEntity    新实体
     * @param oldPaasFormDataEntity 老实体
     * @author feng.zheng
     * @date 2019/1/30 10:19
     */
    protected void packageSaasFormUpdateSaveDTO(SaasFormSaveDTO saasFormSaveDTO, PaasFormDataEntity paasFormDataEntity, PaasFormDataEntity oldPaasFormDataEntity) {
        paasFormDataEntity.setAddTime(oldPaasFormDataEntity.getAddTime());
        saasFormSaveDTO.setIsNew(false);
        saasFormSaveDTO.setOldPaasFormDataEntity(oldPaasFormDataEntity);
        saasFormSaveDTO.setNewPaasFormDataEntity(paasFormDataEntity);
        saasFormSaveDTO.setNewData(paasFormDataEntity.getData());
        saasFormSaveDTO.setOldData(oldPaasFormDataEntity.getData());
    }

    /**
     * 判断当前人有没有编辑的数据权限
     *
     * @param formDataUpdateDTO
     * @param explainMap
     * @param oldPaasFormDataEntity
     * @return
     */
    @Override
    protected void handleEditDataPermission(FormDataUpdateDTO formDataUpdateDTO, Map<String, FieldAttrEntity> explainMap, WorkOrderEntity oldPaasFormDataEntity) throws XbbException {
       // 工单无需判断
    }

    @Override
    protected Integer getFlowStatus(WorkOrderEntity formData) {
        Integer flowStatus = formData.getFlowStatus();
        formData.setFlowStatus(null);
        return flowStatus;
    }

    @Override
    protected void updateFlowStatus(Integer flowStatus, String corpid, Long dataId, Integer saasMark, Integer businessType) throws XbbException{
        // 为了保证用户在有修改数据的时候才触发工作流，将flowStatus进行分开更新
        PaasProcessDataEntity paasProcessDataEntity = new PaasProcessDataEntity();
        paasProcessDataEntity.setCorpid(corpid);
        paasProcessDataEntity.setFormDataId(dataId);
        paasProcessDataEntity.setBusinessType(businessType);
        paasProcessDataEntity.setSaasMark(saasMark);
        formDataHelp.updateFormDataStatus(paasProcessDataEntity, flowStatus);
    }
}
